#include "Engine.h"
#include "VariableDef.h"

#ifdef WIN32
#include <esUtil.h>

// Create a windows
HWND WinCreate(const CHAR *title, INT32 width, INT32 height);

// Create VideoContext
void InitOpenGLES(HWND hWnd, INT32 width, INT32 height);

EGLDisplay display;
EGLContext context;
EGLSurface surface;
int moveMouseX, moveMouseY;
// The main entry

int main(int n, char **args)
{
	BOOL exit = FALSE;
    MSG msg = {0};

    HWND hWnd = WinCreate(TITLE_GAME,  SCREEN_W, SCREEN_H);
    InitOpenGLES(hWnd, SCREEN_W, SCREEN_H);


	//Init app 
	application = new Application();	
	application->Init();
	s_CurrentState = GAMESTATE_LOGO; 
	application->SetState(s_CurrentState);	
    // The main loop

    while (!exit)
    {
        long startFrame = clock();
        int gotMessage = (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) != 0);

        if (gotMessage)
        {
            if (msg.message == WM_QUIT)
            {
                exit = TRUE;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            };
        }
        else
        {
			if (!isInterrupt)
			{
				application->Update();
				application->Render();
			}

            long frameTime = clock() - startFrame;
			if (frameTime < 1000 / VGPConfig::LIMIT_FPS)
            {
               Sleep(1000 / VGPConfig::LIMIT_FPS - frameTime);
            }

            eglSwapBuffers (display, surface);
        }

    };

	application->Destroy();
	
	delete application;
	
	return 0;
}



// FUNCTION FOR CREATING WINDOWS

// WinProc
LRESULT WINAPI WndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
{
    LRESULT  lRet = 1; 
    int x = moveMouseX = LOWORD(lParam); 
    int y = moveMouseY = HIWORD(lParam);
    int key = 0;
    static int mouseDown = false;

    switch (uMsg) 
    { 
    case WM_DESTROY:
        PostQuitMessage(0);
        exit(0);
        break; 
    case WM_LBUTTONDOWN:        
        mouseDown = true;
		application->PointerEvent(POINTER_DOWN, x, y);
        break;

    case WM_MOUSEMOVE:
        if (mouseDown)
        {
            application->PointerEvent(POINTER_DRAGGED, x, y);
        };
        break;

    case WM_LBUTTONUP:
        mouseDown = false;
		application->PointerEvent(POINTER_UP, x, y);
        break;    

    case WM_KEYDOWN:
        x = wParam; // x for key code        
		application->KeyEvent(KEY_DOWN, x);
        break;
	case WM_KEYUP:
		x = wParam; // x for key code        
		application->KeyEvent(KEY_UP, x);
        break;
    default: 
        // return for DefWindowProc Handle
        lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); 
        break; 
    };
    return lRet;
};


// Create a windows
HWND WinCreate(const char *title, int width, int height)
{
    WNDCLASS wndClass = {0};

    DWORD    wStyle   = 0;
    RECT     windowRect;
    HINSTANCE hInstance = GetModuleHandle(NULL);


    wndClass.style         = CS_OWNDC;
    wndClass.lpfnWndProc   = (WNDPROC) WndProc; 
    wndClass.hInstance     = hInstance; 
    wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
	wndClass.lpszClassName = TITLE_GAME;

    // Register Windows Class
    if (!RegisterClass (&wndClass) )
        return FALSE; 

    wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION;
    windowRect.left = 0;
    windowRect.top = 0;
    windowRect.right = width;
    windowRect.bottom = height;

    AdjustWindowRect ( &windowRect, wStyle, FALSE );
    HWND hWnd = CreateWindow(
        TITLE_GAME,
        title,
        wStyle,
        0,
        0,
        windowRect.right - windowRect.left,
        windowRect.bottom - windowRect.top,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, true);
    return hWnd;
};


// Init OpeNGLES
void InitOpenGLES(HWND hWnd, INT32 width, INT32 height)
{
    EGLint numConfigs;
    EGLint majorVersion;
    EGLint minorVersion;

    EGLConfig config;
    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };

    EGLint attribList[] =
    {
        EGL_RED_SIZE, 5,
        EGL_GREEN_SIZE, 6,
        EGL_BLUE_SIZE, 5,
        EGL_ALPHA_SIZE, 0,
        EGL_DEPTH_SIZE, 8,
        EGL_STENCIL_SIZE, 8,
        EGL_SAMPLE_BUFFERS, 1,
        EGL_NONE
    };

    display = eglGetDisplay(GetDC(hWnd));
    if ( display == EGL_NO_DISPLAY )
    {
        LOGE("Cannot Get Display for OPENGLES 2.0");
    }

    // Initialize EGL
    if ( !eglInitialize(display, &majorVersion, &minorVersion) )
    {
        LOGE("Cannot Init OPENGLES 2.0");
    }

    // Get configs
    if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
    {
        LOGE("Cannot get Config for OPENGLES 2.0");
    }

    // Choose config
    if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )
    {
        LOGE("Cannot Chose Config for OPENGLES 2.0");
    }

    // Create a surface
    surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
    if ( surface == EGL_NO_SURFACE )
    {
        LOGE("Cannot Create Window Surface for OPENGLES 2.0");
    }

    // Create a GL context
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
    if ( context == EGL_NO_CONTEXT )
    {
        LOGE("Cannot Create Context for OPENGLES 2.0");
    }   
   
    // Make the context current
    if ( !eglMakeCurrent(display, surface, surface, context) )
    {
        LOGE("Cannot Display Current OPENGLES 2.0");
    }    
}

#endif